package com.Example;

import com.alibaba.fastjson.JSONObject;
import com.client.RepChainClient;
import com.crypto.ECDSASign;
import com.crypto.Sha256;
import com.crypto.SignFunc;
import com.google.protobuf.ByteString;
import com.protos.Peer.*;
import com.crypto.BitcoinUtils;
import com.utils.certUtil;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.binary.Hex;

import java.io.File;
import java.security.PublicKey;
import java.security.cert.Certificate;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class Receive {
    public static void main(String[] args) {
//        String host = "192.168.2.69:8081";
        String host = "localhost:8081";
        RepChainClient client = new RepChainClient(host);
        // 获取块链信息
        JSONObject chainInfo = client.getChainInfo();
        System.out.println(chainInfo);
        //根据txid获取交易
        Transaction tran = client.getTransactionByTxid("f0df1df0-9fd3-11e8-9bab-a5063e3c3e4b");
        // 获得块高度
        int height = chainInfo.getJSONObject("result").getIntValue("height");
        // 根据高度获取块数据
        Block block = client.getBlockByHeight(height);
//        System.out.println(block);  // 打印块
        try {
            // 对立面的交易进行签名验证
            List<Transaction> transactions = block.getTransactionsList();
            // 获取publickey, 短地址与publickey一一对应放到map里
            Map<String, PublicKey> map= new HashMap<String, PublicKey>();
            for (int i = 1; i <= 5; i++) {
                String path = "jks/mykeystore_num.jks";
                path = path.replaceAll("num",String.valueOf(i));
                List list = certUtil.getCertFromJKS(new File(path),"123",String.valueOf(i));
                Certificate cert = (Certificate) list.get(0);
                PublicKey publicKey = (PublicKey) list.get(2);
                String certAddr = BitcoinUtils.calculateBitcoinAddress(publicKey.getEncoded());
                map.put(certAddr,publicKey);
            }

            // 进行签名验证，对块里的每一个交易进行验证
            for (int i = 0; i < transactions.size(); i++){
                Transaction transaction = transactions.get(i);
                String cert = transaction.getCert().toStringUtf8();
                byte[] sig = transaction.getSignature().toByteArray();  // 为验证签名做准备
                Transaction.Builder builder = transaction.toBuilder().setSignature(ByteString.EMPTY).setMetadata(ByteString.EMPTY);
                Transaction tOutSig = builder.build();
                SignFunc signFunc = new ECDSASign();
                Boolean flag = signFunc.verify(sig, Sha256.hash(tOutSig.toByteArray()), map.get(cert));
                System.out.println(flag);   // 输出验证结果
            }
            // currentBlockHash可以查询本块
            Block currentBlock = client.getBlockByBlockHash(chainInfo.getJSONObject("result").getString("currentBlockHash"));
            // previousBlockHash可以查询上一个块
            Block previousBlock = client.getBlockByBlockHash(Base64.encodeBase64String(block.getPreviousBlockHash().toByteArray()));
            String previousBlockHash = chainInfo.getJSONObject("result").getString("previousBlockHash");
//            JSONObject previousBlockJsonObject = client.doGet("http://" + host + "/block/hash/"+previousBlockHash);
//            JSONObject result = previousBlockJsonObject.getJSONObject("result");
//            String json = result.toJSONString();
            try {
//                Block.Builder builder = Block.newBuilder();
//                JsonFormat.parser().merge(json,builder);
//                Block preBlock = builder.build();
                Block preBlock = client.getBlockByBlockHash(previousBlockHash);
//                System.out.println(preBlock);
                //对block进行验证，对block进行hash计算
                //验证previous block的hash值
                byte[] blockHash = Sha256.hash(preBlock.toByteArray());
                String blockHash1 = Hex.encodeHexString(blockHash);
                String blockHash2 = Base64.encodeBase64String(block.getPreviousBlockHash().toByteArray());
                byte[] blockHash3 = Base64.decodeBase64(previousBlockHash);
                System.out.println(new String(blockHash3));
                System.out.println(blockHash2.equals(previousBlockHash));
                System.out.println(blockHash1.equals(block.getPreviousBlockHash().toStringUtf8()));
                System.out.println(blockHash1.equals(new String(blockHash3)));
            } catch (Exception ex) {
                ex.printStackTrace();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}
